package main

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

func main() {
	// 使用“面向对象”的思维方式编写一个学生信息管理系统。
	//学生有id、姓名、年龄、分数等信息
	//程序提供展示学生列表、添加学生、编辑学生信息、删除学生等功能
	Tille()
	SystemStart()

}

//定义学生对象
type Student struct {
	id     int
	name   string
	age    int
	source float64
}

var (
	startid      = 10001
	studenttable []Student
)

//标题
func Tille() {
	fmt.Println("=====================================学生信息管理系统====================================")
	fmt.Println("========================================================================================")
	fmt.Println("========================================================================================")
	fmt.Println("========================================================================================")
	fmt.Println("========================================================================================")
}

//系统启动
func SystemStart() {
	var res string
	var isExit = false
	for {
		fmt.Println("a)学生列表 b)添加学生 c)退出系统")
		//fmt.Println("")
		fmt.Scan(&res)
		if len(res) != 1 {
			fmt.Println("您输入的参数有误，请重新输入")
			continue
		}
		switch {
		case strings.Contains(res, "c"):
			isExit = true
		case strings.Contains(res, "a"):
			fmt.Println("a)学生列表")
			Studentlist()
		case strings.Contains(res, "b"):
			fmt.Println("b)添加学生")
			insertStudent()
		default:
			fmt.Println("c)退出系统")
			fmt.Println("您输入的参数有误，请重新输入")
		}
		if isExit {
			break
		}
	}
	fmt.Println("系统关闭")
}

//添加学生程序
func insertStudent() {
	var student Student
	student.id = startid
	startid++
	var res = make([]string, 4)
	var errs = []string{"请输入学生姓名 c)返回上一级", "请输入学生年龄 c)返回上一级", "请输入学生分数 c)返回上一级", "添加成功 a)继续添加 c)返回上一级(会修改之前的数据) m)返回主菜单"}
	var isfmt = true
	for i := 0; i < len(res); i++ {
		fmt.Println(errs[i])
		fmt.Scan(&res[i])
		if len(res[i]) == 1 && strings.Contains(res[i], "c") {
			i -= 2
		} else {
			switch i {
			case 0:
				student.name = res[i]
			case 1:
				ages, err := strconv.ParseInt(res[i], 10, 8)
				if err != nil {
					isfmt = false
					break
				}
				student.age = int(ages)
			case 2:
				source, err := strconv.ParseFloat(res[i], 2)
				if err != nil {
					isfmt = false
					break
				}
				student.source = source
			case 3:
				studenttable = append(studenttable, student)
				switch {
				case len(res[i]) != 1:
					i -= 1
				case strings.Contains(res[i], "a"):
					insertStudent()
				case strings.Contains(res[i], "m"):
				default:
					i -= 1
				}
			}
			if isfmt != true {
				i -= 1
				fmt.Println("您输入的参数有误，请重新输入")
				isfmt = true
			}
		}
		if i < -1 {
			break
		}
	}
}

//查看学生列表程序
func Studentlist() {
	GetList()
	var res string
	var isExit = false
	for {
		if isExit {
			break
		}
		fmt.Println("e)修改学生信息 d)删除学生 c)返回主菜单")
		fmt.Scan(&res)
		if len(res) != 1 && len(res) != 6 {
			fmt.Println("您输入的参数有误，请重新输入")
			continue
		}
		switch len(res) {
		case 1:
			switch {
			case strings.Contains(res, "e"):
				var eres string
				for {
					fmt.Println("请输入需要修改的学生ID号")
					fmt.Scan(&eres)
					tid, err := chickStudent(eres)
					if err != nil {
						fmt.Println(err)
					} else {
						editStudent(tid)
						GetList()
						break
					}
				}
			case strings.Contains(res, "d"):
				var dres string
				for {
					fmt.Println("请输入需要删除的学生ID号")
					fmt.Scan(&dres)
					tid, err := chickStudent(dres)
					if err != nil {
						fmt.Println(err)
					} else {
						deleteStudent(tid)
						GetList()
						break
					}
				}
			case strings.Contains(res, "c"):
				isExit = true
			default:
				fmt.Println("您输入的参数有误，请重新输入")
			}
		case 6:
			rres := []rune(res)
			rstr := string(rres[0])
			ures := DeleteSliceRune(0, []rune(rres))
			sres := string(ures)
			tid, err := chickStudent(sres)
			if err != nil {
				fmt.Println(err)
				break
			}
			switch {
			case strings.Contains(rstr, "e"):
				editStudent(tid)
				GetList()
			case strings.Contains(rstr, "d"):
				deleteStudent(tid)
				GetList()
			default:
				fmt.Println("您输入的参数有误，请重新输入")
			}
		default:
			fmt.Println("您输入的参数有误，请重新输入")
		}
	}
}

func GetList() {
	fmt.Println("学生ID\t|\t学生姓名\t|\t学生年龄\t|\t学生分数")
	fmt.Println("——————\t|\t————————\t|\t————————\t|\t———————")
	for i := 0; i < len(studenttable); i++ {
		fmt.Println(studenttable[i].id, "\t|\t", studenttable[i].name, "     \t|\t", studenttable[i].age, "     \t|\t", studenttable[i].source)
		fmt.Println("——————\t|\t————————\t|\t————————\t|\t———————")
	}
}

//检查学生是否存在
func chickStudent(str string) (int, error) {
	var res = -1
	var err error
	switch len(str) {
	case 5:
		intres, errs := strconv.ParseInt(str, 10, 64)
		if errs != nil {
			err = errors.New("数据格式错误,请重新输入")
		}
		for i := 0; i < len(studenttable); i++ {
			if intres == int64(studenttable[i].id) {
				res = i
			}
		}
		if res == -1 {
			err = errors.New("该ID不存在,请重新输入")
		}
	case 6:
		ures := DeleteSliceRune(0, []rune(str))
		sres := string(ures)
		intres, errs := strconv.ParseInt(sres, 10, 64)
		if errs != nil {
			err = errors.New("数据格式错误,请重新输入")
		} else {
			for i := 0; i < len(studenttable); i++ {
				if intres == int64(studenttable[i].id) {
					res = i
				}
			}
			if res == -1 {
				err = errors.New("该ID不存在,请重新输入")
			}
		}
	default:
		err = errors.New("数据格式错误,请重新输入")
	}

	return res, err
}

//修改学生信息
func editStudent(tid int) {
	var student = studenttable[tid]
	fmt.Printf("修改学生信息,当前学生为%v\n", student.name)
	ages := strconv.Itoa(student.age)
	sources := strconv.FormatFloat(student.source, 'f', 2, 64)
	var res = []string{student.name, ages, sources, ""}
	var errs = []string{"修改学生姓名,当前姓名为%v c)返回上一级 n)默认不修改 \n", "修改学生年龄,当前年龄为%v c)返回上一级 n)默认不修改 \n", "修改学生分数,当前分数为%v c)返回上一级 n)默认不修改 \n", "修改成功 c)返回上一级(会修改之前的数据) m)返回列表\n"}
	var isfmt = true
	for i := 0; i < len(errs); i++ {
		if i != 3 {
			fmt.Printf(errs[i], res[i])
		} else {
			fmt.Println(errs[i])
		}
		fmt.Scan(&res[i])
		if len(res[i]) == 1 && strings.Contains(res[i], "c") {
			i -= 2
		} else if len(res[i]) == 1 && strings.Contains(res[i], "n") {
			continue
		} else {
			switch i {
			case 0:
				student.name = res[i]
			case 1:
				ages, err := strconv.ParseInt(res[i], 10, 8)
				if err != nil {
					isfmt = false
					break
				}
				student.age = int(ages)
			case 2:
				source, err := strconv.ParseFloat(res[i], 2)
				if err != nil {
					isfmt = false
					break
				}
				student.source = source
			case 3:
				studenttable[tid] = student
				switch {
				case len(res[i]) != 1:
					i -= 1
				case strings.Contains(res[i], "a"):
					insertStudent()
				case strings.Contains(res[i], "m"):
				default:
					i -= 1
				}
			}
			if isfmt != true {
				i -= 1
				fmt.Println("您输入的参数有误，请重新输入")
				isfmt = true
			}
		}
		if i < -1 {
			break
		}
	}
}

//删除学生
func deleteStudent(tid int) {
	studenttable = DeleteSlice(tid, studenttable)
}

//删除指定角标元素
func DeleteSlice(num int, a []Student) []Student {
	a = append(a[:num], a[num+1:]...)
	return a
}

//删除指定角标元素
func DeleteSliceRune(num int, a []rune) []rune {
	a = append(a[:num], a[num+1:]...)
	return a
}
